class FlipDom {
	dom: HTMLElement;
	transition: string;
	firstPosition: { x: number; y: number };
	isPlaying: boolean;
	transitionEndHandler: () => void;

	constructor(dom: Element, duration = 0.5) {
		this.dom = dom as HTMLElement;
		this.transition = typeof duration === 'number' ? `${duration}s` : duration;
		this.firstPosition = { x: null, y: null };
		this.isPlaying = false;
		this.transitionEndHandler = () => {
			this.isPlaying = false;
			this.recordFirst();
		};
	}

	getDomPosition() {
		const rect = this.dom.getBoundingClientRect();
		return { x: rect.left, y: rect.top };
	}

	recordFirst(firstPosition?: { x: number; y: number }) {
		if (!firstPosition) {
			firstPosition = this.getDomPosition();
		}
		this.firstPosition.x = firstPosition.x;
		this.firstPosition.y = firstPosition.y;
	}

	*play() {
		if (!this.isPlaying) {
			this.dom.style.transition = 'none';
			const lastPosition = this.getDomPosition();
			const dis = {
				x: lastPosition.x - this.firstPosition.x,
				y: lastPosition.y - this.firstPosition.y
			};
			if (!dis.x && !dis.y) {
				return;
			}
			this.dom.style.transform = `translate(${-dis.x}px, ${-dis.y}px)`;
			yield 'moveToFirst';
			this.isPlaying = true;
		}

		this.dom.style.transition = this.transition;
		this.dom.style.transform = 'none';
		this.dom.removeEventListener('transitionend', this.transitionEndHandler);
		this.dom.addEventListener('transitionend', this.transitionEndHandler);
	}
}

export class Flip {
	flipDoms: Set<FlipDom>;
	duration: number;

	constructor(doms: HTMLCollection, duration = 0.5) {
		this.flipDoms = new Set([...doms].map((item) => new FlipDom(item, duration)));
	}

	play() {
		// console.log('play')
		let gs = [...this.flipDoms]
			.map((it) => {
				const generator = it.play();
				return {
					generator,
					iteratorResult: generator.next()
				};
			})
			.filter((g) => !g.iteratorResult.done);
		console.log('gs: ', gs);
		while (gs.length > 0) {
			document.body.clientWidth;
			gs = gs
				.map((g) => {
					g.iteratorResult = g.generator.next();
					return g;
				})
				.filter((g) => !g.iteratorResult.done);
		}
	}
}
